package org.mozilla.javascript;

import com.xucia.strands.CoroutineSupport;
import com.xucia.strands.Future;
/**
 * This context factory can do all top call as spawn operations, returning a value normally if they did not suspend
 * execution, returns a {@link Future} if the called operation is suspended. This is the default behavior for this
 * factory, and it is HIGHLY recommended that use this behavior if you are going to be Futures/coroutines,
 * so that the main thread that triggers events does not suspend execution when coroutines suspend.  
 * @author Kris Zyp
 *
 */
public class SpawningContextFactory extends ContextFactory {
	private static boolean spawnTopCallsIfNeeded = true;
	/**
	 * Do all top calls as spawn operations, that is 
		each call will be in a new thread/fiber. If the call finishes without suspending execution then the value is returned.
	 * If the call suspends execution, this will return a future that represents the value to be returned from the future execution.  
	 * @param callable
	 * @param cx
	 * @param scope
	 * @param thisObj
	 * @param args
	 * @return
	 */
	protected Object doTopCall(Callable callable, Context cx, Scriptable scope,
			Scriptable thisObj, Object[] args) {
		if (spawnTopCallsIfNeeded)
			return Future.spawnIfNeeded(callable, cx, scope, thisObj, args);
		else
			return super.doTopCall(callable, cx, scope, thisObj, args);
	}
	
	//TODO: if the Future moves into the mozilla codebase, then this does not need to be public
	/**
	 * Shares a context with the current thread. The current thread should be a fiber that will not 
	 * execute at the same time as other threads that use this context.
	 */
    public static void shareContextWithCurrentFiber(Context cx) {
        Object helper = VMBridge.instance.getThreadContextHelper();
        VMBridge.instance.setContext(helper,cx);    	
    }

	public static boolean isSpawnTopCallsIfNeeded() {
		return spawnTopCallsIfNeeded;
	}

	public static void setSpawnTopCallsIfNeeded(boolean spawnTopCallsIfNeeded) {
		SpawningContextFactory.spawnTopCallsIfNeeded = spawnTopCallsIfNeeded;
	}

}
